home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / games / nhak_src.zip / MAC.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  30KB  |  1,232 lines

  1. /*    SCCS Id: @(#)mac.c    3.0    88/08/05
  2. /*      Copyright (c) Johnny Lee  1989    */ 
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /*    Source file for character I/O and miscellaneous */
  6. /*    user interface routines for the macintosh */
  7.  
  8. #include    "hack.h"
  9.  
  10. /* Global variables */
  11. WindowPtr    HackWindow;    /* points to Hack's window */
  12. extern char    *keys[8];
  13. extern short macflags;
  14. extern long lowMemLimit;
  15. short cursorPos=0;
  16. short repDelay;
  17. long lastMD;
  18. long segments = SEG_DO;
  19. extern short altCurs; /* should be a macflag */
  20.  
  21. int
  22. tgetch()
  23.  
  24. {
  25.     char    ch;
  26.     EventRecord    theEvent;
  27.     Rect cursorRect,box,windowRect;
  28.     long    message,cursorTime,start;
  29.     MenuHandle    theMenu;
  30.     register short    keyCode;
  31.     short    temp;
  32.     term_info    *t;
  33.     GrafPtr    oldPort,oldPort1;
  34.     static char nextCommand;
  35.     short aboutBox();
  36.     char mButtonDown();
  37.     Point    mouseLoc;
  38.     WindowPtr    theWindow;
  39.     void    doUpdate();
  40. #define    clearKey    0x47
  41. #define ESCAPEkey    0x1B
  42.     static int see, saw = 0;
  43.     int eye, cursOff = 100;
  44.     boolean cursRectInv;    /* should be a macflag */
  45.     short    fInFront = TRUE;
  46.  
  47.     t = (term_info *)GetWRefCon(HackWindow);
  48.     mouseLoc.h = (macflags & fMoveWRTMouse) ? t->tcur_x : (u.ux-1);
  49.     mouseLoc.v = (macflags & fMoveWRTMouse) ? t->tcur_y : (u.uy+1);
  50.     cursorRect.left = t->tcur_x * t->charWidth + Screen_Border;
  51.     cursorRect.right = cursorRect.left + t->charWidth - 1;
  52.     cursorRect.top = t->height * t->tcur_y + Screen_Border;
  53.     cursorRect.bottom = cursorRect.top + t->height - 1;
  54.     cursorTime = GetCaretTime();
  55.     box.left = mouseLoc.h * t->charWidth + Screen_Border - 1;
  56.     box.right = box.left + t->charWidth + 2;
  57.     box.top = mouseLoc.v * t->height + Screen_Border - 1;
  58.     box.bottom = box.top + t->height + 2;
  59.     /* permit use of cursor keys and numeric keypad */
  60.     /* does the same translation as in msdos.c but includes cursor keys */
  61.     ch = '\0';
  62.     /* handle extended command from menu */
  63.     if (nextCommand && (macflags & (fExtCmdSeq1 | fExtCmdSeq2 | fExtCmdSeq3))) {
  64.         if (macflags & fExtCmdSeq1) {
  65.         ch = '#';
  66.         macflags = macflags ^ (fExtCmdSeq1 | fExtCmdSeq2);
  67.         } else if (macflags & fExtCmdSeq2) {
  68.         ch = nextCommand;
  69.         macflags = macflags ^ (fExtCmdSeq2 | fExtCmdSeq3);
  70.         if (!(macflags & fExtCmdSeq3))
  71.             nextCommand = '\0';
  72.         } else if (macflags & fExtCmdSeq3) {
  73.         ch = '\r';
  74.         macflags &= ~fExtCmdSeq3;
  75.         }
  76.     }
  77.     GetPort(&oldPort);
  78.     SetPort(HackWindow);
  79.     if (!(macflags & fDoNonKeyEvt)) {
  80.         cursorPos = -1;
  81.         if (! flags.wantspace) SetCursor(&ARROW_CURSOR);
  82.     }
  83.     /* initialize cursor blinking */
  84.     message = TickCount();
  85.     cursRectInv = FALSE;
  86.     while (!ch) {
  87.         (void)WaitNextEvent(everyEvent, &theEvent, (fInFront) ? 0L : 50L, 0L);
  88.         if (theEvent.what == keyDown || theEvent.what == autoKey) {
  89.             ch = 0;
  90.             ObscureCursor();
  91.             /* use raw key codes */
  92.             keyCode = (LoWord(theEvent.message) & keyCodeMask)>>8;
  93.              if (keyCode == clearKey) {
  94.                 macflags = macflags ^ fToggleNumPad;
  95.                 SetWTitle(HackWindow,
  96.                     (macflags & fToggleNumPad)    ? "\016NetHack [MOVE]"
  97.                                                 : "\015NetHack [NUM]");
  98.                 ch = 0;
  99.                 continue;
  100.             }
  101.             if ((macflags & fToggleNumPad) && (keyCode>0x40 &&keyCode < 0x5D) 
  102.                 || (keyCode > 0x7A && keyCode<0x7F)) {
  103.                 ch = t->keyMap[keyCode-65];
  104.                 if ((theEvent.modifiers & shiftKey) && (ch)) {
  105.                     ch = (ch == '.') ? ':' : (char)toupper(ch);
  106.                 }
  107.                 if (ch)
  108.                     break;
  109.             }
  110.             if (t->system.keyBoardType < 4 && keyCode == 50) {
  111.                 ch = (char)ESCAPEkey;    /* ESC */
  112.                 break;
  113.             }            /* make the command key = control key on all non-adb keyboards
  114.                          Now, LEAVE it this way ! Otherwise you'll render non-us
  115. keyboards useless, since here is where "<" and ">" are located */
  116.             if ((theEvent.message & 0xFF) == 0x60) {
  117.                 ch = (char)ESCAPEkey;
  118.                 break;
  119.             } /* This is the way to fix backquote->esc for all macs */
  120.             if (theEvent.modifiers & cmdKey) {
  121.                 ch = (char)(theEvent.message & 0x1F);
  122.                 if(ch == ('Q' & 0x1F)) ch = 'Q'; /* For Quit */
  123.                 break;
  124.             }
  125.             if (theEvent.modifiers & optionKey) {
  126.                 for(start = 43; start < 56; start++) {
  127.                     if (t->keyMap[start] == (char)(theEvent.message & 0xFFL)) {
  128.                         ch = t->keyMap[start - 13];
  129.                         break;
  130.                     }
  131.                 }
  132.             }
  133.             /* not a cursor key or from the numeric keypad */
  134.             if (!ch) {
  135.                 ch = (char)(theEvent.message & 0xFF);
  136.             }
  137.         } else {
  138.         /* what other events to handle */
  139.             switch (theEvent.what) {        
  140.             case nullEvent:
  141.                 if (!fInFront)
  142.                     break;
  143.                 GetPort(&oldPort1);
  144.                 SetPort((GrafPtr)HackWindow);
  145.                 /* wait until something occurs */
  146.                 if ((TickCount() > message) && (FrontWindow() == HackWindow)) {
  147.                     message = TickCount() + cursorTime;
  148.                     InvertRect(&cursorRect);
  149.                     cursRectInv = !cursRectInv;
  150.                 }
  151.                 if (FrontWindow() == HackWindow && (macflags & fDoNonKeyEvt)) {
  152.                     if ((FindWindow(theEvent.where,&theWindow) == inContent)
  153.                         && (macflags & fDoUpdate) && (HackWindow == theWindow)) {
  154.                         
  155.                         GetMouse(&mouseLoc);
  156.                         if (PtInRect(mouseLoc,&box)) {
  157.                             temp = 8;
  158.                         } else {
  159.                             PtToAngle(&box,mouseLoc,&temp);
  160.                             temp = ((temp + 22) / 45) % 8;    /* 0=N, 1=NE ... 7=NW */
  161.                         }
  162.                         /* since we're not doing anything let's look at the cursor */
  163.                         if (altCurs) {    /* this list is prioritized! */
  164.                             if (Sick) {
  165.                                 cursOff = 130;    /* offset for CURS resource set */
  166.                                 see = SICK;
  167.                             } else if (Blind) {
  168.                                 cursOff = 120;
  169.                                 see = BLINDED;
  170.                             } else if (Hallucination) {
  171.                                 cursOff = 110;
  172.                                 see = HALLUC;
  173.                             } else if (Confusion || Stunned) {
  174.                                 see = CONFUSION;
  175.                             } else {
  176.                                 cursOff = 100;
  177.                                 see = 0;
  178.                             }
  179.                         } else {
  180.                             see = (Confusion || Stunned) ? CONFUSION : 0;
  181.                             cursOff = 100;
  182.                         }
  183.                         if ((cursorPos != temp) || (see != saw)) {
  184.                             if (see != saw) {
  185.                                 switch(see) {
  186.                                 case CONFUSION:
  187.                                     break;
  188.                                 default:    /* hmm, a bit much for !altCurs */
  189.                                     for (eye=0; eye<=8; eye++) {
  190.                                         EmptyHandle(t->cursor[eye]);
  191.                                         t->cursor[eye] = GetCursor(eye+cursOff);
  192.                                         HNoPurge(t->cursor[eye]);
  193.                                     }
  194.                                     break;
  195.                                 }
  196.                                 saw = see;
  197.                             }
  198.                             cursorPos = temp;
  199.                             eye = (Confusion || Stunned) ? rn2(9) : temp;
  200.                             SetCursor(*t->cursor[eye]);
  201.                         }
  202.                     } else if (cursorPos>=0) {
  203.                         cursorPos = -1;
  204.                         SetCursor(&ARROW_CURSOR);
  205.                     }
  206.                 }
  207.                 if (StillDown() && cursorPos>=0 && cursorPos < 8
  208.                     && TickCount() > lastMD+repDelay) {
  209.                     ch = mButtonDown(theEvent, t, &nextCommand);
  210.                     if (repDelay) {
  211. #ifdef THINK_C
  212.                         repDelay = KeyRepThresh;
  213. #else
  214.                         repDelay /= 3;
  215. #endif
  216.                     }
  217.                     lastMD = TickCount();
  218.                     /*return ch;*/
  219.                 }            
  220.                 SetPort(oldPort1);
  221.                 break;
  222.             case app4Evt:
  223. #define    kSuspendResumeMessage    1        /* high byte of suspend/resume event message */
  224. #define    kMouseMovedMessage        0xFA    /* high byte of mouse-moved event message */
  225. #define    SuspResIsResume(evtMessage)        ((evtMessage) & 0x00000001)
  226.  
  227.                 switch (theEvent.message >> 24) {
  228.                     case kSuspendResumeMessage:
  229.                         if (!SuspResIsResume(theEvent.message)) {
  230.                         /* ---------- SUSPEND EVENT ------------ */
  231.                             fInFront = FALSE;
  232.                             if (macflags & fZoomOnContextSwitch
  233.                                 && !EmptyRect(&(**(HackWindow)->visRgn).rgnBBox))
  234.                             {
  235.                                 InvalRect(&HackWindow->portRect);
  236.                                 SizeWindow(HackWindow,60,60,FALSE);
  237.                             }
  238.                         } else {
  239.                         /* ---------- RESUME EVENT ------------- */
  240.                             fInFront = TRUE;
  241.                             if (macflags & fZoomOnContextSwitch) {
  242.                                 SizeWindow(HackWindow,
  243.                                  (t->maxCol * t->charWidth) + 2 * Screen_Border,
  244.                                  (t->maxRow * t->height) + 2 * Screen_Border,
  245.                                  TRUE);
  246.                                 SetPort(HackWindow);
  247.                                 InvalRect(&HackWindow->portRect);
  248.                                 if ((int) (theMenu = GetMHandle(editMenu))
  249.                                     && FrontWindow() == HackWindow) {
  250.                                     SetMenuBar(t->fullMBarHandle);
  251.                                     for (temp = fileMenu;temp <= extendMenu;temp++) {
  252.                                     if (temp != editMenu)
  253.                                         EnableItem(GetMHandle(temp), 0);
  254.                                     }
  255.                                     EnableItem(GetMHandle(appleMenu), 1);
  256.                                     DisableItem(theMenu, 0);
  257.                                     DrawMenuBar();
  258.                                 }
  259.                             }
  260.                         }
  261.                         break;
  262.                 }
  263.                 break;
  264.         
  265.             case updateEvt:
  266.                 if (HackWindow == (WindowPtr)theEvent.message) {
  267.                     doUpdate(t);
  268.                     if (cursRectInv) InvertRect(&cursorRect);    /* restore cursor */
  269.                 }
  270.                 break;
  271.                 
  272.             case activateEvt:
  273.                 if (HackWindow == (WindowPtr)theEvent.message) {
  274.                     if (theMenu = GetMHandle(editMenu)) {
  275.                         if (theEvent.modifiers & activeFlag) {
  276.                             if (macflags & fDoUpdate) {
  277.                                 SetMenuBar(t->fullMBarHandle);
  278.                                 for (temp = fileMenu;temp <= extendMenu;temp++) {
  279.                                     if (temp != editMenu)
  280.                                         EnableItem(GetMHandle(temp), 0);
  281.                                 }
  282.                                 EnableItem(GetMHandle(appleMenu), 1);
  283.                             }
  284.                             DisableItem(theMenu, 0);
  285.                         } else {
  286.                             EnableItem(theMenu, 0);
  287.                             if (macflags & fDoUpdate) {
  288.                                 SetMenuBar(t->shortMBarHandle);
  289.                                 for (temp = fileMenu;temp <= extendMenu;temp++) {
  290.                                     if (temp != editMenu)
  291.                                         DisableItem(GetMHandle(temp), 0);
  292.                                 }
  293.                                 DisableItem(GetMHandle(appleMenu), 1);
  294.                             }
  295.                         }
  296.                         DrawMenuBar();
  297.                     }
  298.                 }
  299.                 break;
  300.                 
  301.             case mouseDown:
  302.                 ch = mButtonDown(theEvent, t, &nextCommand);
  303. #ifdef THINK_C
  304.                 repDelay = KeyThresh;
  305. #else
  306.                 repDelay = 42;
  307. #endif
  308.                 lastMD = theEvent.when;
  309.                 break;
  310.             }
  311.         }        
  312.     }
  313.     if (cursRectInv) InvertRect(&cursorRect);
  314.  
  315.     SetPort(oldPort);
  316.     return ((ch == '\r') ? '\n' : ch);
  317. }
  318.  
  319. void
  320. doUpdate(t)
  321. term_info    *t;
  322. {
  323.     register short    temp;
  324.     GrafPtr    oldPort;
  325.     register    short i,j;
  326.     register char    attr, *p;
  327. #ifdef TEXTCOLOR
  328.     if (t->system.hasColorQD) {
  329.         Rect    r;
  330.         GDHandle    gd;
  331.         
  332.         r = (**(*(WindowPeek)HackWindow).contRgn).rgnBBox;
  333.         LocalToGlobal(&r.top);
  334.         LocalToGlobal(&r.bottom);
  335.         gd = GetMaxDevice(&r);
  336.         HLock((Handle)gd);
  337.         t->inColor = (**(**gd).gdPMap).pixelSize > 1;
  338.         HUnlock((Handle)gd);
  339.     }
  340. #endif
  341.     GetPort(&oldPort);
  342.     SetPort((GrafPtr)HackWindow);
  343.     BeginUpdate(HackWindow);
  344.     ForeColor(t->color[0]);
  345.     BackColor(t->color[7]);
  346.     for (i = 0; i<t->maxRow; i++) {
  347.         p = t->scrAttr[i];
  348.         for (j = temp = 0, attr = *p; j<t->maxCol; j +=1, p++) {
  349.             if (*p != attr) {
  350.                 MoveTo(Screen_Border + temp*t->charWidth,
  351.                     t->ascent + (i * t->height) +
  352.                     Screen_Border);
  353.                 if (attr & 0x80) {
  354.                     ForeColor(t->color[7]);
  355.                     BackColor(t->color[0]);
  356.                 } else if (t->inColor) {
  357.                     ForeColor(t->color[attr]);
  358.                      /* yellow fgnd hard to see on white bgnd */
  359.                      /* so change to green background */
  360.                     switch(attr) {
  361.                     case BROWN:
  362.                         BackColor(t->color[GREEN]);
  363.                         break;
  364.                     case BLUE:
  365.                         BackColor(t->color[CYAN]);
  366.                         break;
  367.                     case CYAN:
  368.                         BackColor(t->color[BLUE]);
  369.                         break;
  370.                     default:
  371.                         BackColor(t->color[7]);
  372.                            break;
  373.                     }
  374.                 } else {
  375.                     ForeColor(t->color[0]);
  376.                     BackColor(t->color[7]);
  377.                 }
  378.                 DrawText(&(t->screen[i][temp]), 0, j - temp);
  379.                 temp = j;
  380.                 attr = *p;
  381.             } /* if */
  382.         } /* for j */
  383.         if (temp != t->maxCol) {
  384.             MoveTo(Screen_Border + temp*t->charWidth,
  385.                 t->ascent + (i * t->height) +
  386.                 Screen_Border);
  387.             if (attr & 0x80) {
  388.                 ForeColor(t->color[7]);
  389.                 BackColor(t->color[0]);
  390.             } else if (t->inColor) {
  391.                 ForeColor(t->color[attr]);
  392.                  /* yellow fgnd hard to see on white bgnd */
  393.                  /* so change to green background */
  394.                 switch(attr) {
  395.                 case BROWN:
  396.                     BackColor(t->color[GREEN]);
  397.                     break;
  398.                 case BLUE:
  399.                     BackColor(t->color[CYAN]);
  400.                     break;
  401.                 case CYAN:
  402.                     BackColor(t->color[BLUE]);
  403.                     break;
  404.                 default:
  405.                     BackColor(t->color[7]);
  406.                        break;
  407.                 }
  408.             } else {
  409.                 ForeColor(t->color[0]);
  410.                 BackColor(t->color[7]);
  411.             }
  412.             DrawText(&(t->screen[i][temp]), 0, j - temp);
  413.         } /* if */
  414.     } /* for i */
  415.     EndUpdate(HackWindow);
  416.     SetPort(oldPort);
  417. }
  418.  
  419. char
  420. mButtonDown(theEvent, t, nextCommand)
  421. EventRecord    theEvent;
  422. term_info    *t;
  423. char    *nextCommand;
  424. {
  425.     Rect    boundsRect;
  426.     WindowPtr    theWindow;
  427.     long    message;
  428.     char    deskacc[256];
  429.     MenuHandle    theMenu;
  430.     char    ch;
  431.     short    menuBar;
  432.     GrafPtr    oldPort;
  433.  
  434.     ch = '\0';
  435.     if (macflags & fDoNonKeyEvt) {
  436.         switch (FindWindow(theEvent.where,&theWindow)) {
  437.         case inMenuBar:
  438.         if (!(macflags & fDoMenus))
  439.             break;
  440.         SetCursor(&ARROW_CURSOR);
  441.         message = MenuSelect(theEvent.where);
  442.  
  443.         if (!HiWord(message))
  444.             break;
  445.  
  446.         switch (HiWord(message)) {
  447.             case editMenu:
  448.             (void)SystemEdit((short)message - 1);
  449.             break;
  450.             case appleMenu:
  451.             if (LoWord(message) > 1) {
  452.                 GetItem(GetMHandle(HiWord(message)),LoWord(message),
  453.                     deskacc);
  454.                 SetMenuBar(t->shortMBarHandle);
  455.                 DrawMenuBar();
  456.                 (void)OpenDeskAcc(deskacc);
  457.                 if (theMenu = GetMHandle(editMenu))
  458.                     EnableItem(theMenu, 0);
  459.             } else
  460.                 if (aboutBox(1))
  461.                     ch = '?';
  462.             break;
  463.             case fileMenu:
  464.             case inventMenu:
  465.             case prepMenu:
  466.             case actionMenu:
  467.             case moveMenu:
  468.             *nextCommand =
  469.                 keys[HiWord(message)-appleMenu][LoWord(message)-1];
  470.             ch = (!(*nextCommand)) ? '\0' : (char)ESCAPEkey;
  471.             macflags |= (fExtCmdSeq2 | fExtCmdSeq3);
  472. #ifdef TEXTCOLOR
  473. #define    MAC_BLACK    0
  474. #define    MAC_WHITE    7
  475.             if(HiWord(message) == fileMenu && LoWord(message) == 3) {
  476.                 theMenu = GetMHandle(HiWord(message));
  477.                 macflags = macflags ^ fInvertedScreen;
  478.                 CheckItem(theMenu, 3,
  479.                     (boolean)(macflags & fInvertedScreen));
  480.  
  481.                 /* switch black & white */
  482.                 message = t->color[BLACK];
  483.                 t->color[MAC_BLACK] = t->color[MAC_WHITE];
  484.                 t->color[MAC_WHITE] = message;
  485.  
  486.                 /* switch light blue & dark blue */
  487.                 message = t->color[BLUE];
  488.                 t->color[BLUE] = t->color[CYAN];
  489.                 t->color[CYAN] = message;
  490.  
  491.                 ForeColor(t->color[MAC_BLACK]);
  492.                 BackColor(t->color[MAC_WHITE]);
  493.                 /* refresh screen without prompting 'More' */
  494.                 message = flags.toplin;
  495.                 flags.toplin = 0;
  496.                 docrt();
  497.                 flags.toplin = message;
  498.             }
  499. #endif
  500.             break;
  501.             case extendMenu:
  502.             ch = (char)ESCAPEkey;
  503.             *nextCommand =
  504.              keys[HiWord(message) - appleMenu][LoWord(message) - 1];
  505.             macflags |= fExtCmdSeq1;
  506.             break;
  507.         }
  508.         HiliteMenu(0);
  509.         break;
  510.         
  511.         case inSysWindow:
  512.         SystemClick(&theEvent, theWindow);
  513.         break;
  514.  
  515.         case inDrag:
  516.         if (!(theEvent.modifiers & cmdKey)) {
  517.             if (theWindow != FrontWindow()) {
  518.                 SelectWindow(theWindow);
  519.                 break;
  520.             }
  521.         }
  522.         menuBar = (ROM85 == -1) ? 20 : GetMBarHeight();
  523.  
  524.         {
  525.         RgnHandle fooRgn = GetGrayRgn();
  526.             boundsRect = (*fooRgn)->rgnBBox;
  527.         }
  528.         SetCursor(&ARROW_CURSOR);
  529.         DragWindow(theWindow, theEvent.where, &boundsRect);
  530.         break;
  531.     
  532.     case inContent:
  533.         if (theWindow != FrontWindow()) {
  534.             SelectWindow(theWindow);
  535.         } else if (theWindow == HackWindow) {
  536.             Point    mouseLoc;
  537.             Rect    box;
  538.             short    temp;
  539.  
  540.             if(flags.wantspace) {
  541.                 ch = 0x20;
  542.             } else {
  543.                 box.left = (u.ux-1) * t->charWidth + Screen_Border + (t->charWidth/2);
  544.                 box.right = box.left + 1;
  545.                 box.top = (u.uy+1) * t->height + Screen_Border + t->height/2;
  546.                 box.bottom = box.top + 1;
  547.                 GetMouse(&mouseLoc);
  548.                 PtToAngle(&box,mouseLoc,&temp);
  549.                 temp = ((temp + 22) / 45) % 8;    /* ~same as above */
  550.                 switch(cursorPos) {
  551.                     case 0:
  552.                         ch = 'k';
  553.                         break;
  554.                     case 1:
  555.                         ch = 'u';
  556.                         break;
  557.                     case 2:
  558.                         ch = 'l';
  559.                         break;
  560.                     case 3:
  561.                         ch = 'n';
  562.                         break;
  563.                     case 4:
  564.                         ch = 'j';
  565.                         break;
  566.                     case 5:
  567.                         ch = 'b';
  568.                         break;
  569.                     case 6:
  570.                         ch = 'h';
  571.                         break;
  572.                     case 7:
  573.                         ch ='y';
  574.                         break;
  575.                     case 8:
  576.                         ch = '.';
  577.                         break;
  578.                 }
  579.                 if ((theEvent.modifiers & shiftKey) && (ch)) {
  580.                     ch = (ch == '.') ? ':' : (char)toupper(ch);
  581.                 }
  582.             }
  583.         }            
  584.         break;
  585.         }
  586.     } else {
  587.         switch (FindWindow(theEvent.where,&theWindow)) {
  588.         case inContent:
  589.             if(flags.wantspace) ch = 0x20;
  590.             break;
  591.         default:
  592.             break;
  593.         }
  594.     }
  595.     return ch;
  596. }
  597.  
  598. void
  599. gethdate(name) char *name;
  600. {
  601. /*end gethdate*/}
  602.  
  603. int
  604. uptodate(fd)
  605. {
  606.     return(1);
  607. }
  608.  
  609. #ifndef THINKC4
  610. char *
  611. getenv(s)
  612. char *s;
  613. {
  614.     return((char *)NULL);
  615. }
  616.  
  617. int
  618. memcmp(x,y,n)
  619. char *x,*y;
  620. int    n;
  621.  
  622. {
  623.     int i;
  624.     
  625.     i = 0;
  626.     while (i++< n && (*x++) == (*y++)) {
  627.         /*x++; y++; i++*/
  628.         ;
  629.     }
  630.     if (i != n)
  631.         return ((*x > *y) ? -1 : 1);
  632.     else
  633.         return (0);
  634. }
  635. #else
  636. int
  637. kbhit()
  638. {    
  639.     EventRecord    theEvent;
  640.     
  641.     SystemTask();
  642.     return (EventAvail(keyDownMask | mDownMask, &theEvent));
  643. }
  644. #endif
  645.  
  646. #ifdef AZTEC
  647.  
  648. sleep(x)
  649. int    x;
  650. {
  651.     long t;
  652.     
  653.     Delay((long)x, &t);
  654. }
  655. #endif
  656.     
  657.  
  658. int
  659. mcurs(col,row)
  660. short    col,row;
  661.  
  662. {
  663.     term_info    *t;
  664.     
  665.     t = (term_info *)GetWRefCon(HackWindow);
  666.     t->tcur_y = row;
  667.     t->tcur_x = col;
  668.     return 1;
  669. }
  670.  
  671. static void
  672. checkScroll(t)
  673. term_info *t;
  674. {
  675.     if (t->tcur_y >= t->maxRow-1) {
  676.         short    temp;
  677.         char    *s, *s1;
  678.  
  679.         BlockMove((Ptr)t->screen[1], (Ptr)t->screen[0],
  680.             (Size)((t->maxRow - 1) * t->maxCol));
  681.         BlockMove((Ptr)t->scrAttr[1], (Ptr)t->scrAttr[0],
  682.             (Size)((t->maxRow - 1) * t->maxCol));
  683.         for (temp = 0, s = t->screen[t->maxRow - 1], s1 = t->scrAttr[t->maxRow - 1];
  684.                 temp < t->maxCol; temp++, s++, s1++) {
  685.             *s = ' ';
  686.             *s1 = 0;
  687.         }
  688.         {
  689.             Pattern p, o;
  690.             Rect    window;
  691.             
  692.             if (macflags & fInvertedScreen) {
  693.                 BlockMove((Ptr)&((GrafPtr)HackWindow)->bkPat, (Ptr)&o,
  694.                         sizeof(Pattern));
  695.                 GetIndPattern(&p, sysPatListID,1);
  696.                 BackPat(p);
  697.             }
  698.             window = HackWindow->portRect;
  699.             InsetRect(&window, 4,4);
  700.             window.top += t->height;
  701.             ScrollRect(&window, 0, -t->height,
  702.                     ((WindowPeek)HackWindow)->updateRgn);
  703.             ValidRect(&window);
  704.             if (macflags & fInvertedScreen) {
  705.                 BackPat(o);
  706.             }
  707.         }
  708.         t->tcur_y = t->maxRow - 1;
  709.     }
  710. }
  711.  
  712. void
  713. mput(s)
  714. char    *s;
  715. {
  716.     unsigned short    sLen,temp;
  717.     GrafPtr        prevPort;
  718.     register term_info    *t;
  719.     Point        cur;
  720.     register short        x,y;
  721.     Rect        eraseRect;
  722.     register char        *stmp,*c,*c1;
  723.     char    savech;
  724.     
  725.     t = (term_info *)GetWRefCon(HackWindow);
  726.     sLen = strlen(s);
  727.     
  728.     x = t->tcur_x;
  729.     y = t->tcur_y;
  730.     if (y >= t->maxRow)
  731.         panic("mput - incorrect cursor position\n");
  732.     cur.h = (x * t->charWidth) + Screen_Border;
  733.     cur.v = t->ascent + (y * t->height) + Screen_Border;
  734.     GetPort(&prevPort);
  735.     SetPort((GrafPtr)HackWindow);
  736.     TextFont(t->fontNum);
  737.     TextSize(t->fontSize);
  738.     TextMode(srcCopy);
  739.     /* a termcap-type escape string */
  740.     if (!strncmp(s, "\033[", 2)) {
  741.         switch(*(s + 2)) {
  742.         case 'c':    /* color kluge */
  743.             temp = (short)(*(s + 3) - 'a');
  744.             t->curAttr = temp;
  745.             if (temp >= BLACK && temp < MAXCOLORS &&
  746.                 (temp % (MAXCOLORS / 2) != GRAY)) /* set colour */
  747.                 t->curAttr = temp % (MAXCOLORS / 2);
  748.             if ((temp & 0x07) == GRAY)
  749.                 t->curAttr = 0;
  750.             if (t->inColor) {
  751.             if (temp >= BLACK && temp < MAXCOLORS &&
  752.                 (temp % (MAXCOLORS / 2) != GRAY)) /* set colour */
  753.                 ForeColor(t->color[temp % (MAXCOLORS / 2)]);
  754.             if (temp == GRAY)
  755.                         ForeColor(t->color[0]);
  756.              /* yellow fgnd hard to see on white bgnd */
  757.              /* so change to green background */
  758.             if (temp == YELLOW || temp == BROWN)
  759.                 BackColor(t->color[GREEN]);
  760.             if (temp == BLUE)
  761.                 BackColor(t->color[CYAN]);
  762.             if (temp == CYAN)
  763.                 BackColor(t->color[BLUE]);
  764.             }
  765.             break;
  766.         case '0':    /* normal video begin */
  767.             if (*(s + 3) == 'm') {
  768.                 ForeColor(t->color[0]);
  769.                 BackColor(t->color[7]);
  770.                 t->curHilite = FALSE;
  771.                 t->curAttr = 0;
  772.             }
  773.             break;
  774.         case '1':    /* inverse video begin */
  775.             if (*(s + 3) == 'm') {
  776.                 ForeColor(t->color[7]);
  777.                 BackColor(t->color[0]);
  778.                 t->curHilite = TRUE;
  779.                 t->curAttr = 0;
  780.             }
  781.             break;
  782.         case 'A':    /* cursor up */
  783.             if (y > 0) {
  784.                 t->tcur_y--;
  785.                 cur.v -= t->height;
  786.             }
  787.             break;
  788.         case 'B':    /* cursor down */
  789.             if (y < t->maxRow) {
  790.                 t->tcur_y++;
  791.                 cur.v += t->height;
  792.             }
  793.             break;
  794.         case 'C':    /* cursor right */
  795.             if (x < t->maxCol) {
  796.                 t->tcur_x++;
  797.                 cur.h += t->charWidth;
  798.             }
  799.             break;
  800.         case 'D':    /* cursor left */
  801.             if (x > 0) {
  802.                 t->tcur_x--;
  803.                 cur.h -= t->charWidth;
  804.             }
  805.             break;
  806.         case 'H':    /* home cursor */
  807.             t->tcur_x = t->tcur_y = 0;
  808.             cur.h = Screen_Border;
  809.             cur.v = t->ascent + Screen_Border;
  810.             break;
  811.         case 'K':    /* clear to end of line */
  812.             eraseRect.top = cur.v - (t->ascent);
  813.             eraseRect.left = cur.h;
  814.             eraseRect.bottom = eraseRect.top + t->height;
  815.             eraseRect.right = (t->maxCol*t->charWidth) + Screen_Border;
  816.             EraseRect(&eraseRect);
  817.             for (temp = x, c = &(t->screen[y][x]), c1 = &(t->scrAttr[y][x]);
  818.                 temp < t->maxCol; temp++) {
  819.                 *c++ = ' ';
  820.                 *c1++ = 0;
  821.             }
  822.             break;
  823.         case '2':
  824.             if (*(s+3) == 'J') {    /* clear screen */
  825.             x = y = t->tcur_x = t->tcur_y = 0;
  826.             eraseRect.top = eraseRect.left = Screen_Border;
  827.             eraseRect.bottom = t->maxRow*t->height + Screen_Border;
  828.             eraseRect.right = t->charWidth*t->maxCol + Screen_Border;
  829.             EraseRect(&eraseRect);
  830.             for (y = 0, c = t->screen[0], c1 = t->scrAttr[0];
  831.                 y < t->maxCol * t->maxRow; y++) {
  832.                     *c++ = ' ';
  833.                     *c1++ = 0;
  834.             }
  835.             cur.h = Screen_Border;
  836.             cur.v = t->ascent + Screen_Border;
  837.             }
  838.             break;
  839.         }
  840.         MoveTo(cur.h, cur.v);
  841.     } else {
  842.         short    charleft = sLen;
  843.         
  844.         MoveTo(cur.h, cur.v);
  845.         stmp = s;
  846.         
  847.         if (sLen) {
  848.         while (stmp < (s + sLen)) {
  849.             temp = (x + charleft - 1 < t->maxCol - 1) ? charleft : t->maxCol - x;
  850.             savech = '\0';
  851.             c1 = stmp + temp;    /* point to the char after the end */
  852.             c = index(stmp, '\n');
  853.             if (c && c < c1) {
  854.                 c1 = c;
  855.                 savech = '\n';
  856.                 temp = (short)(c - stmp);
  857.                 /* don't want to include '\n' in print */
  858.             }
  859.             c = index(stmp, '\r');
  860.             if (c && c < c1) {
  861.                 c1 = c;
  862.                 savech = '\r';
  863.                 temp = (short)(c - stmp);
  864.                 /* don't want to include '\r' in print */
  865.             }
  866.             DrawText((Ptr)stmp, 0, temp);
  867.             BlockMove((Ptr)stmp, (Ptr)&(t->screen[y][x]), (long)temp);
  868.             memset(&(t->scrAttr[y][x]), ((t->curHilite) ? 128 : 0) + t->curAttr,
  869.                 temp);
  870.             stmp += temp + 1;
  871.             charleft -= temp + 1;
  872.             if (!savech) {
  873.                 t->tcur_x += temp;
  874.             }
  875.  
  876.             if (t->tcur_x >= t->maxCol-1 || savech) {
  877.                 if (savech != '\r') {
  878.                     if (t->tcur_y >= t->maxRow-1) {
  879.                         checkScroll(t);
  880.                     } else {
  881.                         y = (++t->tcur_y);
  882.                     }
  883.                 }
  884.     
  885.                 x = t->tcur_x = 0;
  886.                 cur.h = Screen_Border;
  887.                 cur.v = y * t->height + t->ascent + Screen_Border;
  888.                 MoveTo(cur.h,cur.v);
  889.             }
  890.         }
  891.     }
  892.     }
  893.     if (t->tcur_x >= t->maxCol-1) {
  894.         t->tcur_x = t->tcur_x % t->maxCol;
  895.         t->tcur_y++;
  896.         checkScroll(t);
  897.     }
  898.     SetPort(prevPort);
  899. }
  900.  
  901. int
  902. mputc(c)
  903. char    c;
  904. {
  905.     GrafPtr        prevPort;
  906.     register term_info    *t;
  907.     Point        cur;
  908.     register short        x,y;
  909.     Rect        eraseRect;
  910.     char        savech;
  911.     PenState    pnState;
  912.     
  913.     t = (term_info *)GetWRefCon(HackWindow);
  914.     
  915.     x = t->tcur_x;
  916.     y = t->tcur_y;
  917.     cur.h = (x * t->charWidth) + Screen_Border;
  918.     cur.v = t->ascent + (y * t->height) + Screen_Border;
  919.     GetPort(&prevPort);
  920.     SetPort((GrafPtr)HackWindow);
  921.     TextFont(t->fontNum);
  922.     TextSize(t->fontSize);
  923.     TextMode(srcCopy);
  924.     
  925.     MoveTo(cur.h, cur.v);
  926.     savech = '\0';
  927.     if (c == '\b') {
  928.         if (x > 0) {
  929.             c = ' ';
  930.             x = (--t->tcur_x);
  931.             cur.h = (x * t->charWidth) + Screen_Border;
  932.             Move(-t->charWidth,0);
  933.             savech = '\b';
  934.         } else if (y > 0) {
  935.                 c = ' ';
  936.                 x = t->tcur_x = (t->maxCol - 1);
  937.                 y = (--t->tcur_y);
  938.                 cur.h = (x * t->charWidth) + Screen_Border;
  939.                 cur.v -= t->height;
  940.                 MoveTo(cur.h, cur.v);
  941.                 savech = '\b';
  942.         }
  943.     }
  944.     if (c == '\007') {
  945.         SysBeep(1);
  946.     } else if ((c == '\n') || (c == '\r')) {
  947.         t->tcur_x = 0;
  948.         if (t->tcur_y >= t->maxRow && c == '\r') {
  949.             t->tcur_y = t->maxRow - 1;
  950.         } else if (c == '\n') {
  951.             if (t->tcur_y >= t->maxRow-1) {
  952.                 checkScroll(t);
  953.             } else {
  954.                 t->tcur_y++;
  955.             }
  956.         }
  957.     } else {
  958.         t->screen[y][x] = c;
  959.         t->scrAttr[y][x] = ((t->curHilite) ? 128 : 0) + t->curAttr;
  960.         DrawText(&c, 0, 1);
  961.         if (!savech) {
  962.             t->tcur_x++;
  963.             if (t->tcur_x >= t->maxCol)
  964.             {
  965.                 t->tcur_x = 0;
  966.                 t->tcur_y++;
  967.                 checkScroll(t);
  968.             }
  969.         }
  970.     }
  971.     cur.h = (t->tcur_x * t->charWidth) + Screen_Border;
  972.     cur.v = t->ascent + (t->tcur_y * t->height) + Screen_Border;
  973.     MoveTo(cur.h,cur.v);
  974.  
  975.     SetPort(prevPort);    
  976.     return 1;
  977. }
  978.  
  979. int
  980. mputs(s)
  981. char    *s;
  982. {
  983.     mput(s);
  984.     return 1;
  985. }
  986.         
  987.         
  988.         
  989. int
  990. mprintf(fstr)
  991. char    *fstr;
  992. {
  993. #define    Bufsz    14        
  994.     char        numAsStr[Bufsz];
  995.     short        numsz;
  996.     char        *ps;
  997.     unsigned long    num;
  998.  
  999.     boolean        convchar;
  1000.     boolean        islong;
  1001.     char        c;
  1002.     char        *s;
  1003.     char        prBuffer[128];
  1004.     register char        *pb;
  1005.     
  1006.     prBuffer[0] = '\0';
  1007.     pb = &prBuffer[0];
  1008.     ps = (char *)&fstr;    /* convert to pointer to params */
  1009.     ps += sizeof(char *);    /* skip over format string ptr */
  1010.     while (*fstr)    {
  1011.         s = index(fstr, '%');
  1012.         if (s) {
  1013.         num = (short)(s - fstr);
  1014.         strncpy(pb, fstr, (short)num);
  1015.         pb += num;
  1016.         fstr = s;
  1017.         } else {
  1018.         Strcpy(pb, fstr);
  1019.         fstr += strlen(fstr)-1;
  1020.         }
  1021.         switch (*fstr) {
  1022.         case '%':
  1023.             fstr++;
  1024.             convchar = FALSE;
  1025.             islong = FALSE;
  1026.             do {
  1027.             switch (*fstr) {
  1028.                 case 'l':    /* long */
  1029.                 islong = TRUE;
  1030.                 fstr++;
  1031.                 break;
  1032.                 case 'u':    /* unsigned decimal */
  1033.                 case 'd':    /* signed decimal */
  1034.                 num = (islong) ? *(unsigned long *)ps
  1035.                            : *(unsigned short *)ps;
  1036.                 numsz = (islong) ? sizeof(long) : sizeof(short);
  1037.                 ps += numsz;
  1038.                 s = (islong) ? fstr - 2 : fstr - 1;
  1039.                 c = *(fstr + 1);
  1040.                 *(fstr + 1) = '\0';
  1041.                 if (islong)
  1042.                     Sprintf(numAsStr, s, num);
  1043.                 else
  1044.                     Sprintf(numAsStr, s, (short)num);
  1045.                 *(fstr + 1) = c;
  1046.                 Strcpy(pb, numAsStr);
  1047.                 pb = (char *)(pb + strlen(numAsStr));
  1048.                 convchar = TRUE;
  1049.                 break;
  1050.                 case 's':
  1051.                 s = *(char **)ps;
  1052.                 Strcpy(pb, s);
  1053.                 pb = (char *)(pb + strlen(s));
  1054.                 ps += sizeof(char *);
  1055.                 convchar = TRUE;
  1056.                 break;
  1057.                 case 'c':
  1058.                 c = *(unsigned short *)ps;
  1059.                 numsz = sizeof(short);
  1060.                 (*pb++) = (char)c;
  1061.                 (*pb) = '\0';
  1062.                 convchar = TRUE;
  1063.                 ps += numsz;
  1064.                 break;
  1065.                 default:
  1066.                 convchar = TRUE;
  1067.             }
  1068.             } while (!convchar);
  1069.             break;
  1070.         default:
  1071.             break;
  1072.         }
  1073.         fstr++;
  1074.     }
  1075.     if (prBuffer[0])
  1076.         mput(&prBuffer[0]);
  1077.         
  1078.     return 1;
  1079. }
  1080.  
  1081. DialogTHndl
  1082. centreDlgBox(resNum, clip)
  1083. short    resNum;
  1084. Boolean    clip;
  1085. {
  1086.     DialogTHndl    th = (DialogTHndl) GetResource('DLOG', resNum);
  1087.     Rect    rect;
  1088.     short    dv, dh;
  1089.  
  1090.     /* centre dialog box on screen */
  1091.     if (th) {
  1092.         rect = SCREEN_BITS.bounds;
  1093.         HLock((Handle)th);
  1094.         dv = ((**th).boundsRect.bottom - (**th).boundsRect.top)/2;
  1095.         dv -= (clip) ? 20 : 0;
  1096.         dh = ((**th).boundsRect.right - (**th).boundsRect.left)/2;
  1097.     
  1098.         (**th).boundsRect.bottom =
  1099.                 (rect.bottom + rect.top + MBarHeight)/2 + dv;
  1100.         (**th).boundsRect.top     =
  1101.                 (rect.bottom + rect.top + MBarHeight)/2 - dv;
  1102.         (**th).boundsRect.right     = (rect.right + rect.left)/2 + dh;
  1103.         (**th).boundsRect.left     = (rect.right + rect.left)/2 - dh;
  1104.         HUnlock((Handle)th);
  1105.     } else
  1106.         panic("Couldn't load dialog resource");    
  1107.  
  1108.     return th;
  1109. }
  1110.  
  1111. short
  1112. aboutBox(prompt)
  1113. short    prompt;
  1114. {
  1115. #define    OK_BUTTON    1
  1116. #define    MORE_INFO_BUTTON    2
  1117.  
  1118.     DialogPtr    theDialog;
  1119.     Rect    rect;
  1120.     Handle    theControl;
  1121.     short    type,itemHit;
  1122.     GrafPtr    oldPort;
  1123.     EventRecord    theEvent;
  1124.     term_info    *t;
  1125.     DialogTHndl    th;
  1126.  
  1127.     /* if about box on startup, centre about box on screen */
  1128.     if (!prompt) {
  1129.         th = centreDlgBox(129, TRUE);
  1130.     }
  1131.  
  1132.     GetPort(&oldPort);
  1133.     theDialog = GetNewDialog(129, (Ptr)NULL,(WindowPtr)-1);
  1134.     if (!prompt) {
  1135.         HideDItem(theDialog, OK_BUTTON);
  1136.         HideDItem(theDialog, MORE_INFO_BUTTON);
  1137.     } else
  1138.         MoveWindow((WindowPtr)theDialog, LEFT_OFFSET, TOP_OFFSET, TRUE);
  1139.  
  1140.     ShowWindow((WindowPtr)theDialog);
  1141.     SetPort(theDialog);
  1142.     TextFont(1);    /* 9 pt. Geneva */
  1143.     TextSize(9);
  1144.     DrawDialog(theDialog);
  1145.     itemHit = 0;
  1146.     if (prompt) {
  1147.         /* BOLD the OK button */
  1148.         GetDItem(theDialog, OK_BUTTON, &type, &theControl, &rect);
  1149.         PenSize(3,3);    
  1150.         InsetRect(&rect,-4,-4);
  1151.         FrameRoundRect(&rect,16,16);
  1152.         PenSize(1,1);
  1153.         while ((itemHit != OK_BUTTON) && (itemHit != MORE_INFO_BUTTON)) {
  1154.             ModalDialog(NULL, &itemHit);
  1155.         }
  1156.     } else {
  1157.         long    tickNum;
  1158.  
  1159.         tickNum = TickCount() + 180;    /* 3 second wait max */
  1160.         while (!itemHit && TickCount()<tickNum) {
  1161.         /*    SystemTask();*/
  1162.             if (GetNextEvent(everyEvent,&theEvent))
  1163.                 if (theEvent.what == mouseDown ||
  1164.                           theEvent.what == keyDown ||
  1165.                       theEvent.what == autoKey)
  1166.                     itemHit = OK_BUTTON;
  1167.         }
  1168.     }
  1169.     DisposDialog(theDialog);
  1170.     ReleaseResource((Handle)th);
  1171.     SetPort(oldPort);
  1172.     return (itemHit == MORE_INFO_BUTTON);
  1173. }
  1174.  
  1175. void
  1176. freeSegs(segs)
  1177. long    *segs;
  1178. {
  1179.     register long s;
  1180.     
  1181.     s = (segs == (long *)0) ? 0L : (*segs);
  1182.     
  1183.     UnloadSeg(dothrow);
  1184.     UnloadSeg(dowear);
  1185.     UnloadSeg(ddocall);
  1186.     UnloadSeg(castmu);
  1187.     UnloadSeg(doforce);
  1188.     if (!(s & SEG_EAT))
  1189.         UnloadSeg(doeat);
  1190.     if (!(s & SEG_ZAP))
  1191.         UnloadSeg(dozap);
  1192.     UnloadSeg(initterm);
  1193.     if (!(s & SEG_APPLY))
  1194.         UnloadSeg(doapply);
  1195.     UnloadSeg(dokick);
  1196.     UnloadSeg(outrumor);
  1197.     if (!(s & SEG_DO))
  1198.         UnloadSeg(steal);
  1199.     UnloadSeg(done1);
  1200.     if (!(s & SEG_POTION))
  1201.         UnloadSeg(dodrink);
  1202.     UnloadSeg(doturn);
  1203. #ifdef REINCARNATION
  1204.     UnloadSeg(makeroguerooms);
  1205. #endif
  1206. #ifdef STRONGHOLD
  1207.     UnloadSeg(load_special);
  1208. #endif
  1209.     UnloadSeg(mklev);
  1210. #ifdef MUSIC
  1211.     if (!(s & SEG_SPELL))
  1212.         UnloadSeg(do_play_instrument);
  1213. #endif
  1214. #ifdef SPELLS
  1215.     if (!(s & SEG_SPELL))
  1216.         UnloadSeg(docast);
  1217. #endif
  1218.     UnloadSeg(savebones);
  1219.     UnloadSeg(expels);
  1220.     UnloadSeg(attack);
  1221.     UnloadSeg(doname);
  1222.     if (FreeMem() < lowMemLimit)
  1223.     {
  1224.         long    space;
  1225.         
  1226.         space = 0x7FFFFFFFL;
  1227.         MaxMem(&space);
  1228.     }
  1229.  
  1230. }
  1231.  
  1232.